﻿using System;
using TMPro;
using UnityEngine;
using Yzq.DAL;

namespace Yzq.BLL
{
    /// <summary>
    /// 1.0 定义一个接口，用于将所有设置项的组件统一处理
    /// </summary>
    public interface ISettingItem
    {
        object GetValue();
        void SaveChangeOfInputField();
        string GetStringValue();
        void Save();
        void Load();
    }

    /// <summary>
    /// 1.1 为每种类型的设置项定义一个组件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class SettingItem<T> : ISettingItem
    {
        /// <summary>
        /// 用来PlayerPref持久化SL的键
        /// </summary>
        public string SettingIdentifier { get; private set; }
        private T DefaultValue;
        public T Value { get; private set; }
        private readonly TMP_InputField _inputField;
        private readonly ISettingTypeHandler<T> _handler;
        private readonly IDataAccess<T> _dataAccess; // 依赖注入的数据访问对象

        /// <summary>
        /// 1.1.1 构造函数，用于初始化设置项
        /// </summary>
        /// <param name="settingIdentifier">用于 PlayerPref 持久化的键</param>
        /// <param name="defaultValue"> 默认值，设计核心，参考其类型绑定对应的处理器 </param>
        /// <exception cref="InvalidOperationException"></exception>
        public SettingItem(string settingIdentifier, T defaultValue, TMP_InputField field, bool PlayerPrefsSL = true)
        {

            SettingIdentifier = settingIdentifier;
            DefaultValue = defaultValue;
            _inputField = field;
            _handler = Activator.CreateInstance(typeof(T).GetHandlerType()) as ISettingTypeHandler<T> ?? 
                throw new ArgumentNullException($"Handler for type {typeof(T)} could not be created.");
            
            _dataAccess = PlayerPrefsSL ? Activator.CreateInstance(typeof(T).GetPlayerPrefAccessType()) as IDataAccess<T> ??
                throw new ArgumentNullException("Access for type {typeof(T)} could not be created.") : null;
            // todo 从其他数据访问对象中加载值

            Load(); // 初始化时加载值
        }

        public object GetValue() => Value;
        public string GetStringValue() => _handler.T2String(Value);

        public bool CheckCorrectChangeOfInputField()
        {
            string _text = _inputField.text;
            return _handler.TryParse(_text, out T parsedValue) && !parsedValue.Equals(Value);
        }
        /// <summary>
        /// 1.1.3 从字符串设置值
        /// </summary>
        /// <param name="inputfield"></param>
        public void SaveChangeOfInputField()
        {
            string _text = _inputField.text;
            if (_handler.TryParse(_text, out T parsedValue))
            {
                Value = parsedValue;
                Save();
            }
            else
            {
                Debug.LogError($"Invalid inputfield '{_text}' for setting: {SettingIdentifier}");
            }
        }

        public void Save()
        {
            try
            {
                _dataAccess.Save(SettingIdentifier, Value);
            }
            catch (Exception ex)
            {
                Debug.LogError($"Error saving setting '{SettingIdentifier}': {ex.Message}");
            }
        }

        public void Load()
        {
            try
            {
                Value = _dataAccess.Load(SettingIdentifier, DefaultValue);
            }
            catch (Exception ex)
            {
                Debug.LogError($"Error loading setting '{SettingIdentifier}': {ex.Message}. Using default value.");
                Value = DefaultValue;
            }
        }
    }
}
